package ro.inf.bomberman;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.StringTokenizer;

/**
 * Das Spielermodell (die Daten).
 * @author Chris
 */
public class PlayerModel {

    private final static String pathName = "BombermanSave.txt";
    private String playerData = "";
    private String name;
    private long highscore;
    private long playedGames;

    //	--------------------	public-Methoden -------------------
    // ------ Konstruktoren ------
    /**
     * Konstruktor des PlayerModel mit Parameter
     *
     * @author Chris
     * @param name
     */
    public PlayerModel(String name) {

        this.name = name;

        if (nameRegistered(name) == true) {
            readPlayerScores();
        } else if (nameRegistered(name) == false) {
            addNewPlayer();
            readPlayerScores();
        }

        writePlayerData();
    }

    /**
     * Konstruktor des PlayerModel wird fuer das Auslesen der Spieler Datei
     * benoetigt
     *
     * @author Chris
     */
    public PlayerModel() {
        readPlayerData();
        readPlayerScores();
    }

    //	--------------------	save-Methode 	-------------------
    /**
     * Speichert die Spieler Datei in die save.txt Datei
     *
     * @author Chris
     * @return boolean
     */
    public boolean saveData() {

        if (writePlayerData() == true) {
            return true;
        } else if (writePlayerData() == false);

        return false;
    }

    //	--------------------	nameRegistered-Methode -------------------
    /**
     * Geht die Spieler Datei mit dem Tokenizer durch und ueberprueft ob der
     * Spieler Name schon vorhanden ist
     *
     * @author Chris
     * @param name
     * @return boolean
     */
    public boolean nameRegistered(String name) {

        this.name = name;

        readPlayerData();

        StringTokenizer tok = new StringTokenizer(playerData);

        if (playerData.length() > 0) {
            while (tok.hasMoreTokens() != false) {
                if (tok.nextToken().toLowerCase().equals(name.toLowerCase())) {
                    return true;
                }
            }
        }

        return false;
    }

    //	--------------------	updateHighscore-Methode -------------------
    /**
     * Setzt die neuen Spieler Highscore und gespielten Spiele + 1 in der
     * Spieler Datei Danach werd die neue Spieler Datei gespeichert mit der
     * Methode writePlayerData
     *
     * @author Chris
     * @param gameScore
     * @return boolean
     */
    public boolean updateHighscore(long gameScore) {

        readPlayerData();
        readPlayerScores();

        this.highscore = this.highscore + gameScore;

        StringTokenizer tok = new StringTokenizer(playerData);
        int countTokens = tok.countTokens();
        boolean stop = false;
        String[] arr = new String[countTokens];
        String s = "";

        // Schreibt ein neues Array mit den Tokens der Spieler Datei
        for (int i = 0; i < countTokens; i++) {
            arr[i] = tok.nextToken();
        }

        // Prueft wo Spieler sich im Array befindet
        // Schreibt den neuen Highscore und die gespielten Spiele
        int k = 0;

        while (k < arr.length - 2 && stop == false) {
            if (arr[k].equals(this.name)) {
                arr[k + 1] = String.valueOf(this.highscore);
                arr[k + 2] = String.valueOf(this.playedGames + 1);
                stop = true;
            }
            k++;
        }

        // Wandelt das Array in einen String zurueck
        for (int l = 0; l < arr.length; l++) {
            s = s + arr[l] + " ";
        }

        this.playerData = s;

        if (writePlayerData() == true) {
            return true;
        } else if (writePlayerData() == false);

        return false;
    }

    //	--------------------	Getter-Methoden	-------------------
    /**
     * Gibt die aktuelle Anzahl der gespielten Spiele vom Spieler zurueck
     *
     * @author Chris
     * @return long
     */
    public long getPlayedGames() {

        readPlayerScores();

        return this.playedGames;
    }

    /**
     * Gibt die aktuelle Anzahl des Highscores vom Spieler zurueck
     *
     * @author Chris
     * @return long
     */
    public long getHighscore() {

        readPlayerScores();

        return this.highscore;
    }

    /**
     * Sucht nach denm Spieler Namen in der Spieler Datei und setzt die
     * Variablen highscore un playedGames
     *
     * @author Chris
     * @param name
     * @return PlayerModel
     */
    public PlayerModel getPlayerModelByName(String name) {

        this.name = name;

        readPlayerData();
        readPlayerScores();

        return this;
    }

    //	--------------------	GUI-Methoden	-------------------
    /**
     * Methode zum Anzeigen der Spieler die der Spieler Datei sind Prueft ob in
     * Spieler Datei Spieler stehen Methode soll auf der GUI erscheinen
     *
     * @author Chris
     * @return String[]
     */
    public String[] showPlayer() {

        readPlayerData();

        StringTokenizer tok = new StringTokenizer(playerData);
        int counts = tok.countTokens();

        if (playerData.length() == 0) {
            //	System.out.println("Keine Spieler vorhanden");
            String[] sarr = new String[1];
            sarr[0] = ("Kein_Spieler");

            return sarr;
        } else {
            String[] splitResult = playerData.split(" ");
            String[] sarr = new String[counts / 3];
            int k = 0;

            for (int i = 0; i < splitResult.length; i = i + 3) {
                //	System.out.println(splitResult[i].toString());
                sarr[k] = splitResult[i].toString();
                k++;
            }

            return sarr;
        }
    }

    /**
     * Methode zum Anzeigen der Spieler Datei mit Punkte und gespielte Spiele
     * Prueft ob in Spieler Datei Spieler Dateien stehen Methode soll auf der
     * GUI erscheinen
     *
     * @author Chris
     * @return String[]
     */
    public String[] showPlayerData() {

        readPlayerData();

        StringTokenizer tok = new StringTokenizer(playerData);
        int counts = tok.countTokens();

        if (playerData.length() == 0) {
            String[] sarr = new String[1];
            sarr[0] = ("Kein Spielerdatei");

            return sarr;
        } else {

            String[] sarr = new String[counts];

            for (int i = 0; i < counts; i++) {
                sarr[i] = tok.nextToken();
            }

            return sarr;
        }
    }

    //	--------------------	private-Methoden ------------------
    //	--------------------	Read-Methoden	-------------------
    /**
     * Laedt die vorhandene Spieler Datei sonst writeNewPlayerData Nach
     * writeNewPlayerData wird Spieler Datei nochmal geladen Loescht ebenso das
     * auftretende ? am Ende von der Spieler Datei
     *
     * @author Chris
     * @param s wird befuellt mit Spieler Datei
     * @return playerDate
     */
    private String readPlayerData() {

        String s = "";
        byte zeichen;

        try {
            FileInputStream leseStrom = new FileInputStream(pathName);

            do {
                zeichen = (byte) leseStrom.read();
                s += (char) zeichen;
            } while (zeichen != -1);

            leseStrom.close();

        } catch (IOException readPlayerDataIOException) {
            writeNewPlayerData();
            readPlayerData();
        }

        StringBuffer buf = new StringBuffer(s);

        for (int i = 0; i < buf.length(); i++) {
            if (buf.charAt(i) == (char) -1) {
                buf.deleteCharAt(i);
            }
        }

        return playerData = buf.toString();
    }

    /**
     * Liest den Spieler Highscore und die gespielten Spiele ein und setzt diese
     * auf den aktuellen Wert
     *
     * @author Chris
     */
    private void readPlayerScores() {

        StringTokenizer tok = new StringTokenizer(playerData);

        while (tok.hasMoreTokens() != false) {
            if (tok.nextToken().equals(this.name)) {
                this.highscore = Long.parseLong(tok.nextToken());
                this.playedGames = Long.parseLong(tok.nextToken());
            }
        }
    }

    //	--------------------	Write-Methoden	-------------------
    /**
     * Erstellt eine neue Spieler Datei Wird nur aufgerufen falls keine Spieler
     * Datei existiert Die readPlayerData Methode ruft sich nochmal auf um leere
     * Spieler Datei zu laden
     *
     * @author Chris
     */
    private void writeNewPlayerData() {

        String newPlayerData = "";

        try {
            FileOutputStream playerData = new FileOutputStream(pathName);

            for (int i = 0; i < newPlayerData.length(); i++) {
                playerData.write((byte) newPlayerData.charAt(i));
            }
            playerData.close();

        } catch (IOException writeNewPlayerDataIOException) {
            //System.out.println("Error bei writeNewPlayerData");
        }
    }

    /**
     * Zum Schreiben der Spieler Datei Methode kann jederzeit aufgerufen werden
     * um Spieler Datei zu sichern
     *
     * @author chris
     * @return boolean
     */
    private boolean writePlayerData() {

        try {
            FileOutputStream writePlayerData = new FileOutputStream(pathName);

            for (int i = 0; i < playerData.length(); i++) {
                writePlayerData.write((byte) playerData.charAt(i));
            }
            writePlayerData.close();

            return true;

        } catch (IOException writePlayerDataIOException) {
            return false;
        }
    }

    //	--------------------	Other-Methoden	-------------------
    /**
     * Fuegt den neuen Spieler der Spieler Datei hinzu Neuer Spieler erhaelt
     * highscore 0 und playedGames 0
     *
     * @author Chris
     * @return playerData
     */
    private String addNewPlayer() {

        playerData = playerData + this.name + " 0 0 ";

        return playerData;
    }
}